package ro.ase.catalog.security.dao.hibernate;

import org.apache.log4j.Logger;
import org.hibernate.Query;
import org.hibernate.Transaction;
import org.hibernate.classic.Session;
import org.springframework.beans.factory.annotation.Autowired;
import ro.ase.catalog.beans.*;
import ro.ase.catalog.beans.dto.AverageDTO;
import ro.ase.catalog.beans.dto.StudentDTO;
import ro.ase.catalog.beans.dto.TeacherDisciplineStudentsDTO;
import ro.ase.catalog.dao.hibernate.GenericDAOImpl;
import ro.ase.catalog.security.dao.IStudentDAO;
import ro.ase.catalog.security.dao.ITeacherDAO;
import ro.ase.catalog.security.dao.ITeacherDisciplineClassDAO;
import ro.ase.catalog.security.dao.IUserDAO;

import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;


/**
 * Created with IntelliJ IDEA.
 * User: Ioana
 * Date: 5/12/14
 * Time: 2:35 PM
 * To change this template use File | Settings | File Templates.
 */
public class StudentDAOImpl extends GenericDAOImpl<Student, Integer> implements IStudentDAO {

     @Autowired
    private IUserDAO userDAO;
    private static final Logger logger = Logger.getLogger(StudentDAOImpl.class);
    @Autowired
    private ITeacherDisciplineClassDAO teacherDisciplineClassDAO;
    public Boolean saveTransactionalStudent(User user, Student student) {
        Session session=null;
        Transaction transaction=null;
        Boolean success=true;
        try{
            session =getSessionFactory().openSession();
            transaction = session.beginTransaction();
            userDAO.save(user);
            save(student);
            transaction.commit();

        }catch(RuntimeException e){
            try{
                transaction.rollback();
                logger.error("Tranzactia nu s-a putut realiza cu succes  "+e.getMessage());
                success=false;
            }
            catch(RuntimeException rbe){
                logger.error(rbe.getMessage());
                success=false;
            }
        }finally{
            if(session!=null){
                session.close();
            }
        }
        return success;
    }

    public List<StudentDTO> findByName(String searchName, int start, int limit) {
        List<Student> studentList;
        if(searchName==null||searchName.equals(""))
        {
            studentList=getHibernateTemplate().find("select s from  Student s ");
        }
        else{
            studentList=getHibernateTemplate().find("select s from  Student s where s.lastName like ?", searchName+"%");
        }
        if(studentList.size()>0 ){
            List<StudentDTO> studentDTOs=new ArrayList<StudentDTO>();
            for(int i=0;i<studentList.size();i++){
                StudentDTO studentDTO=new StudentDTO();
                studentDTO.setId(studentList.get(i).getId());
                studentDTO.setLastName(studentList.get(i).getLastName());
                studentDTO.setFirstName(studentList.get(i).getFirstName());
                studentDTO.setUserName(studentList.get(i).getUser().getLoginname());
                studentDTO.setAddress(studentList.get(i).getAddress());
                studentDTO.setPhone(studentList.get(i).getPhone());
                if(studentList.get(i).getSchoolClass()!=null)
                    studentDTO.setClassName(studentList.get(i).getSchoolClass().getName());
                else
                    studentDTO.setClassName("-");
                studentDTOs.add(studentDTO);
            }
            return  studentDTOs;
        }
        return null;

    }

    public List<TeacherDisciplineStudentsDTO> findAllStudentsByClass(Teacher teacher, SchoolClass schoolClass) {
        List<Student> studentList;
        List<Long> gradeList;
        List<Long> absenceList;
        List <TeacherDisciplineStudentsDTO> studentsDTOs=new ArrayList<TeacherDisciplineStudentsDTO>();

        studentList=getHibernateTemplate().find("select s from  Student s where  s.aSchoolClass like ?", schoolClass);
        for(int i=0;i<studentList.size();i++)
        studentsDTOs.add(getAvgForStudentAtDiscipline(teacher, studentList.get(i)));
        return studentsDTOs;
    }

    public TeacherDisciplineStudentsDTO getAvgForStudentAtDiscipline(Teacher teacher, Student studentList) {
        List<Long> gradeList;
        List<Long> absenceList;

            List<Grade> gradesSem1;
            List<Grade> gradesSem2;

            Grade tezaSem1=null;
            Grade tezaSem2=null;

            Double avgSem1=0.0;
            Double avgSem2=0.0;
            Double totalAverage=0.0;

            gradesSem1=getHibernateTemplate().find("select g from  Grade g, TeacherDisciplineClass tdc where g.student=?  and g.teacherDisciplineClass=tdc and tdc.teacher=? and g.date<='2014-02-14 00:00:00.0 '", new Object[]{studentList,teacher });
            gradesSem2=getHibernateTemplate().find("select g from  Grade g, TeacherDisciplineClass tdc where g.student=?  and g.teacherDisciplineClass=tdc and tdc.teacher=? and g.date>'2014-02-14 00:00:00.0 '", new Object[]{studentList,teacher });
            if(gradesSem1.size()>0&&gradesSem1.get(0)!=null)
            {
                for(int j=0; j<gradesSem1.size();j++)
                {
                     if(gradesSem1.get(j).getTeza()!=null && gradesSem1.get(j).getTeza().equals(true))
                     {
                         tezaSem1=gradesSem1.get(j);
                     }
                     else
                     {
                           avgSem1=avgSem1+gradesSem1.get(j).getValue().doubleValue();
                     }
                }
                if(tezaSem1!=null &&((gradesSem1.size()-1)!=0))
                {
                    avgSem1=(3*(avgSem1/(gradesSem1.size()-1))+tezaSem1.getValue().doubleValue() )/4;

                }
                else
                {
                    avgSem1=avgSem1/gradesSem1.size();

                }
            }

            if(gradesSem2.size()>0&&gradesSem2.get(0)!=null )
            {
                for(int j=0; j<gradesSem2.size();j++)
                {
                    if(gradesSem2.get(j).getTeza()!=null && gradesSem2.get(j).getTeza().equals(true))
                    {
                        tezaSem2=gradesSem2.get(j);
                    }
                    else
                    {
                        avgSem2=avgSem2+gradesSem2.get(j).getValue().doubleValue();
                    }
                }


                if(tezaSem2!=null&&((gradesSem2.size()-1)!=0))
                {
                    avgSem2=(3*(avgSem2/(gradesSem2.size()-1))+tezaSem2.getValue().doubleValue() )/4;

                }
                else
                {
                    avgSem2=avgSem2/gradesSem2.size();
                }
            }

            gradeList=getHibernateTemplate().find("select count(g) from  Grade g, TeacherDisciplineClass tdc where g.student=?  and g.teacherDisciplineClass=tdc and tdc.teacher=? ", new Object[]{studentList,teacher });
            absenceList=getHibernateTemplate().find("select count(abs) from  Absence abs, TeacherDisciplineClass tdc where abs.student=?  and abs.teacherDisciplineClass=tdc and tdc.teacher=? ", new Object[]{studentList,teacher });
            TeacherDisciplineStudentsDTO teacherDisciplineStudentsDTO=new TeacherDisciplineStudentsDTO();
            teacherDisciplineStudentsDTO.setId(studentList.getId());
            teacherDisciplineStudentsDTO.setLastName(studentList.getLastName());
            teacherDisciplineStudentsDTO.setFirstName(studentList.getFirstName());
            teacherDisciplineStudentsDTO.setGradeNo(Integer.valueOf(gradeList.get(0).intValue()));
            teacherDisciplineStudentsDTO.setAbsenceNo(absenceList.get(0).intValue());

            BigDecimal averageSem1=BigDecimal.valueOf(avgSem1).round(new MathContext(1, RoundingMode.HALF_UP));
            BigDecimal averageSem2=BigDecimal.valueOf(avgSem2).round(new MathContext(1, RoundingMode.HALF_UP));

            teacherDisciplineStudentsDTO.setFirstSemAvg(averageSem1);
            teacherDisciplineStudentsDTO.setSecondSemAvg(averageSem2);

            totalAverage=(averageSem1.doubleValue()+averageSem2.doubleValue())/2;


            teacherDisciplineStudentsDTO.setFinalAvg(BigDecimal.valueOf(totalAverage));


       return teacherDisciplineStudentsDTO;
    }

    public Student getStudentByUserName(String loginname) {
        List<Student> studentList=getHibernateTemplate().find("select s from Student s where s.user.loginname=?", loginname);

         return studentList.get(0);
    }
    public List<Student> getStudentsByClass(SchoolClass schoolClass) {
        List<Student> studentList=getHibernateTemplate().find("select s from Student s where s.aSchoolClass=?", schoolClass);

        return studentList;
    }

    public List<AverageDTO> getAverageByClasses(SchoolClass classMaster) {
        List<AverageDTO>  averageDTOs=new ArrayList<AverageDTO>();
        List<Student> studentList=getStudentsByClass(classMaster);
        List<TeacherDisciplineClass> teacherDisciplineClasses=teacherDisciplineClassDAO.getAllDisciplinesByStudent(studentList.get(0)) ;
        for(int i=0;i<studentList.size();i++){
            AverageDTO averageDTO=new AverageDTO();
            averageDTO.setId(i);
            averageDTO.setDisplayName(studentList.get(i).getLastName()+" "+studentList.get(i).getFirstName());
            BigDecimal avgSem1= new BigDecimal(0);
            BigDecimal avgSem2= new BigDecimal(0);
            for(int j=0;j<teacherDisciplineClasses.size();j++){
                TeacherDisciplineStudentsDTO teacherDisciplineStudentsDTO=getAvgForStudentAtDiscipline(teacherDisciplineClasses.get(j).getTeacher(),studentList.get(i));
                  avgSem1=avgSem1.add(teacherDisciplineStudentsDTO.getFirstSemAvg());
                  avgSem2=avgSem2.add(teacherDisciplineStudentsDTO.getSecondSemAvg());
            }
            avgSem1=avgSem1.divide(new BigDecimal(teacherDisciplineClasses.size()));
            averageDTO.setAvgSem1(avgSem1);
            avgSem2=avgSem2.divide(new BigDecimal(teacherDisciplineClasses.size()));
            averageDTO.setAvgSem2(avgSem2);
            BigDecimal finalAvg=(avgSem1.add(avgSem2)).divide(new BigDecimal(2)) ;
            averageDTO.setTotalAvg(finalAvg);
            averageDTOs.add(averageDTO);
        }
        return averageDTOs;  //To change body of implemented methods use File | Settings | File Templates.
    }

    public IUserDAO getUserDAO() {
        return userDAO;
    }

    public void setUserDAO(IUserDAO userDAO) {
        this.userDAO = userDAO;
    }
}
